#!/bin/bash
#
# Copyright (c) 2011 Volodymyr M. Lisivka <vlisivka@gmail.com>, All Rights Reserved
#
# This file is part of bash-modules (http://trac.assembla.com/bash-modules/).
#
# bash-modules is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 2.1 of the License, or
# (at your option) any later version.
#
# bash-modules is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with bash-modules  If not, see <http://www.gnu.org/licenses/>.


[ "${__parser__DEFINED:-}" == "yes" ] || {
  __parser__DEFINED="yes"
  
  . import.sh strings

  parser_summary() {
    echo "TODO."
  }

  parser_usage() {
    echo '

    generate_input_tokenizer STRING=ACTION[...]

        Generate shell function, which will execute given action(s) when
input will match given string(s).

'
  }

  generate_input_tokenizer() {
    local IFS=$'\n'
    local TOKENIZER_COMMAND_PREFIX="${TOKENIZER_COMMAND_PREFIX:-}"
    local TOKENIZER_DEFAULT_ACTION="${TOKENIZER_DEFAULT_ACTION:- : }"
    local TOKENIZER_TOP_LEVEL_DEFAULT_ACTION="${TOKENIZER_TOP_LEVEL_DEFAULT_ACTION:- : }"
    local __TOKENIZER_READ_ERROR_HANDLER='{ if [ $? -gt 128 ]; then continue ; else break ; fi ; }'
    local TOKENIZER_READ_ERROR_HANDLER="${TOKENIZER_READ_ERROR_HANDLER:-$__TOKENIZER_READ_ERROR_HANDLER}"
    local TOKENIZER_ACTION_ERROR_HANDLER="${TOKENIZER_ACTION_ERROR_HANDLER:-break}"
    local TOKENIZER_DEFAULT_ACTION_ERROR_HANDLER="${TOKENIZER_DEFAULT_ACTION_ERROR_HANDLER:-$TOKENIZER_ACTION_ERROR_HANDLER}"
    local TOKENIZER_TOP_LEVEL_DEFAULT_ACTION_ERROR_HANDLER="${TOKENIZER_TOP_LEVEL_DEFAULT_ACTION_ERROR_HANDLER:-$TOKENIZER_DEFAULT_ACTION_ERROR_HANDLER}"

    if [ -z "${__IND:-}" ]
    then
      local TOP_LEVEL="yes"
      echo '
# Generated by bash-modules/keyboard_input_tokenizer.sh written by Volodymyr M. Lisivka <vlisivka@gmail.com>
'
      echo 'IFS=""'
      echo 'TOKENIZER_KEY_SEQUENCE=""'
    else
      local TOP_LEVEL="no"
    fi

    if [ -z "${1%=*}" ]
    then
      # Leaf: execute command.  Return, if action returned non-zero exit code.
      echo "${__IND}${TOKENIZER_COMMAND_PREFIX:-}${1#=} || $TOKENIZER_ACTION_ERROR_HANDLER"
      return 0
    fi

    local __IND="${__IND:-}    "
    echo "${__IND}read -t ${TOKENIZER_READ_TIMEOUT_TIME:-1} -s -r -N 1 TOKENIZER_KEY || $TOKENIZER_READ_ERROR_HANDLER"
    echo "${__IND}TOKENIZER_KEY_SEQUENCE=\"\$TOKENIZER_KEY_SEQUENCE\$TOKENIZER_KEY\""
    echo "${__IND}case \"\$TOKENIZER_KEY\" in"

    # Create map of characters: place each character into it position in array.
    # Will not work for unicode characters.
    local CHARS=( ) KEY CHAR CODE
    for KEY in "$@"
    do
      CHAR="${KEY:0:1}"
      ord CODE "$CHAR"
      CHARS[$CODE]="$CHAR"
    done

    local I
    for I in "${CHARS[@]}"
    do
      case "$I" in
        $'\001') echo  "${__IND}  \$'\\001')" ;;
        $'\002') echo  "${__IND}  \$'\\002')" ;;
        $'\003') echo  "${__IND}  \$'\\003')" ;;
        $'\004') echo  "${__IND}  \$'\\004')" ;;
        $'\005') echo  "${__IND}  \$'\\005')" ;;
        $'\006') echo  "${__IND}  \$'\\006')" ;;
        $'\007') echo  "${__IND}  \$'\\007')" ;;
        $'\010') echo  "${__IND}  \$'\\x7f'|\$'\\cH')" ;; # Backspace or old delete key
        $'\011') echo  "${__IND}  \$'\\t')" ;;
        ''|$'\n') echo  "${__IND}  \$'\\n')" ;;
        $'\013') echo  "${__IND}  \$'\\013')" ;;
        $'\014') echo  "${__IND}  \$'\\014')" ;;
        $'\015') echo  "${__IND}  \$'\\r')" ;; # Does not work, because \r is discarded by read
        $'\016') echo  "${__IND}  \$'\\016')" ;;
        $'\017') echo  "${__IND}  \$'\\017')" ;;
        $'\020') echo  "${__IND}  \$'\\020')" ;;
        $'\021') echo  "${__IND}  \$'\\021')" ;;
        $'\022') echo  "${__IND}  \$'\\022')" ;;
        $'\023') echo  "${__IND}  \$'\\023')" ;;
        $'\024') echo  "${__IND}  \$'\\024')" ;;
        $'\025') echo  "${__IND}  \$'\\025')" ;;
        $'\026') echo  "${__IND}  \$'\\026')" ;;
        $'\027') echo  "${__IND}  \$'\\027')" ;;
        $'\030') echo  "${__IND}  \$'\\030')" ;;
        $'\031') echo  "${__IND}  \$'\\031')" ;;
        $'\032') echo  "${__IND}  \$'\\032')" ;;
        $'\033') echo  "${__IND}  \$'\\e')" ;; # Escape character
        $'\034') echo  "${__IND}  \$'\\034')" ;;
        $'\035') echo  "${__IND}  \$'\\035')" ;;
        $'\036') echo  "${__IND}  \$'\\036')" ;;
        $'\037') echo  "${__IND}  \$'\\037')" ;;
        $'\x7f') echo  "${__IND}  \$'\\x7f'|\$'\\cH')" ;; # Backspace or old delete key
        "'") echo "${__IND}  \"$I\")" ;;
        # Override default action
        *) echo "${__IND}  '$I')";;
      esac

      local J PARAMS=( )
      for J in "$@"
      do
        [[ "$J" != "$I"* ]] || {
          PARAMS[${#PARAMS[@]}]="${J#?}"
        }
      done
      generate_input_tokenizer "${PARAMS[@]}"
      echo "${__IND}  ;;"
    done
    # For any other key, execute default action. Return, if default action returned non-zero exit code.
    if [ "$TOP_LEVEL" == "yes" ]
    then
      echo "${__IND}  *) $TOKENIZER_TOP_LEVEL_DEFAULT_ACTION  || $TOKENIZER_TOP_LEVEL_DEFAULT_ACTION_ERROR_HANDLER ;;"
    else
      echo "${__IND}  *) $TOKENIZER_DEFAULT_ACTION  || $TOKENIZER_DEFAULT_ACTION_ERROR_HANDLER ;;"
    fi
    echo "${__IND}esac"
  }

}
